package com.xbts.system.service.impl;

import cn.hutool.core.thread.ThreadUtil;
import com.huaweicloud.sdk.bss.v2.BssClient;
import com.huaweicloud.sdk.bss.v2.model.RenewalResourcesRequest;
import com.huaweicloud.sdk.bss.v2.model.RenewalResourcesResponse;
import com.huaweicloud.sdk.bss.v2.region.BssRegion;
import com.huaweicloud.sdk.core.auth.BasicCredentials;
import com.huaweicloud.sdk.core.auth.GlobalCredentials;
import com.huaweicloud.sdk.core.auth.ICredential;
import com.huaweicloud.sdk.core.exception.ConnectionException;
import com.huaweicloud.sdk.core.exception.RequestTimeoutException;
import com.huaweicloud.sdk.core.exception.ServiceResponseException;
import com.huaweicloud.sdk.core.utils.JsonUtils;
import com.huaweicloud.sdk.ecs.v2.EcsClient;
import com.huaweicloud.sdk.ecs.v2.model.*;
import com.huaweicloud.sdk.ecs.v2.region.EcsRegion;
import com.huaweicloud.sdk.eip.v2.model.*;
import com.huaweicloud.sdk.eip.v3.EipClient;
import com.huaweicloud.sdk.eip.v3.model.DisassociatePublicipsRequest;
import com.huaweicloud.sdk.eip.v3.model.DisassociatePublicipsResponse;
import com.huaweicloud.sdk.eip.v3.region.EipRegion;
import com.huaweicloud.sdk.evs.v2.EvsClient;
import com.huaweicloud.sdk.evs.v2.model.CreateVolumeRequest;
import com.huaweicloud.sdk.evs.v2.model.CreateVolumeRequestBody;
import com.huaweicloud.sdk.evs.v2.model.CreateVolumeResponse;
import com.huaweicloud.sdk.evs.v2.region.EvsRegion;
import com.huaweicloud.sdk.iam.v3.model.Domains;
import com.huaweicloud.sdk.vpc.v2.model.ListVpcsRequest;
import com.huaweicloud.sdk.vpc.v2.VpcClient;
import com.huaweicloud.sdk.vpc.v2.model.ListVpcsResponse;
import com.huaweicloud.sdk.vpc.v2.region.VpcRegion;
import com.xbts.common.core.domain.AjaxResult;
import com.xbts.common.enums.ServerStatusEnum;
import com.xbts.common.enums.SettingEnum;
import com.xbts.common.exception.ServiceException;
import com.xbts.common.utils.StringUtils;
import com.xbts.system.domain.dto.*;
import com.xbts.system.service.ICloudControlService;
import com.xbts.system.service.ICloudServiceService;
import com.xbts.system.service.ICnUserCloudServersRelationService;
import com.xbts.system.service.SettingService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @Author llk
 * @Date 2023/8/7 9:50
 */
@Service
@Slf4j
public class CloudControlServiceImpl implements ICloudControlService {

    @Autowired
    private SettingService settingService;

    @Autowired
    private ICloudServiceService cloudServiceService;
    @Autowired
    private ICnUserCloudServersRelationService userCloudServersRelationService;

    @Override
    public ListServersDetailsResponse listServersDetails(ListServersDetailsRequestDTO listServersDetailsRequest) {
        EcsClient client = getClient(listServersDetailsRequest.getRegionId());
        ListServersDetailsResponse response = null;
        try {
            response = client.listServersDetails(listServersDetailsRequest);
        } catch (ConnectionException | RequestTimeoutException e) {
            e.printStackTrace();
        } catch (ServiceResponseException e) {
            log.error("查询云服务器详情列表失败: " + e);
        }
        return response;
    }

    @Override
    public AjaxResult batchStopServers(BatchStopServersRequestBodyDTO batchStopServersRequestBodyDTO) {
        EcsClient client = getClient(batchStopServersRequestBodyDTO.getRegionId());
        BatchStopServersResponse response = null;
        BatchStopServersRequest request = new BatchStopServersRequest();

        BatchStopServersRequestBody body = new BatchStopServersRequestBody();
        BeanUtils.copyProperties(batchStopServersRequestBodyDTO, body);
        request.setBody(body);
        try {
            response = client.batchStopServers(request);
            // 更新用户关联的云服务器状态
            userCloudServersRelationService.updateCloudServiceStatusByServerIds(body.getOsStop().getServers(), ServerStatusEnum.SHUTOFF);
        } catch (ConnectionException | RequestTimeoutException e) {
            e.printStackTrace();
        } catch (ServiceResponseException e) {
            log.error("关闭云服务器失败: " + e);
            if (e.getHttpStatusCode() == 400 && e.getErrorCode().equals("Ecs.0000")) {
                return AjaxResult.error("请求数据错误");
            }
        }
        if (response != null) {
            return AjaxResult.success(response);
        }
        return AjaxResult.error("关闭云服务器失败");
    }

    @Override
    public AjaxResult batchStartServers(BatchStartServersRequestBodyDTO batchStartServersRequestBody) {
        EcsClient client = getClient(batchStartServersRequestBody.getRegionId());
        BatchStartServersRequest request = new BatchStartServersRequest();
        BatchStartServersRequestBody body = new BatchStartServersRequestBody();
        BeanUtils.copyProperties(batchStartServersRequestBody, body);
        request.setBody(body);
        BatchStartServersResponse response = null;
        try {
            response = client.batchStartServers(request);
            // 更新用户关联的云服务器状态
            userCloudServersRelationService.updateCloudServiceStatusByServerIds(body.getOsStart().getServers(), ServerStatusEnum.ACTIVE);
        } catch (ConnectionException | RequestTimeoutException e) {
            e.printStackTrace();
        } catch (ServiceResponseException e) {
            log.error("开启云服务器失败: " + e);
        }
        if (response != null) {
            return AjaxResult.success(response);
        }
        return AjaxResult.error("开启云服务器失败");
    }

    @Override
    public AjaxResult batchRebootServers(BatchRebootServersRequestBodyDTO batchRebootServersRequestBodyDTO) {
        log.debug("重启云服务器参数: " + batchRebootServersRequestBodyDTO.toString());
        EcsClient client = getClient(batchRebootServersRequestBodyDTO.getRegionId());
        BatchRebootServersRequest request = new BatchRebootServersRequest();
        BatchRebootServersRequestBody body = new BatchRebootServersRequestBody();
        BeanUtils.copyProperties(batchRebootServersRequestBodyDTO, body);
        request.setBody(body);
        BatchRebootServersResponse response = null;
        try {
            response = client.batchRebootServers(request);
            // 更新用户关联的云服务器状态
            userCloudServersRelationService.updateCloudServiceStatusByServerIds(body.getReboot().getServers(), ServerStatusEnum.REBOOT);
            // 异步查询服务器重启过后的状态
            asyncQueryStatus(body.getReboot().getServers());
        } catch (ConnectionException | RequestTimeoutException e) {
            e.printStackTrace();
        } catch (ServiceResponseException e) {
            log.error("重启云服务器失败: " + e);
        }
        if (response != null) {
            return AjaxResult.success(response);
        }
        return AjaxResult.error("重启云服务器失败");
    }

    /**
     * 异步查询并更新服务器状态
     * @param servers 服务器
     */
    private void asyncQueryStatus(List<ServerId> servers) {
        ThreadUtil.execAsync(() -> {
            try {
                // 暂停五秒后查询
                Thread.sleep(5 * 1000);
                ListServersDetailsRequestDTO service = new ListServersDetailsRequestDTO();
                String serviceIdsStr = servers.stream().map(ServerId::getId).collect(Collectors.joining(","));
                service.setServerId(serviceIdsStr);
                // 重试5次
                for (int i = 0; i < 5; i++) {
                    ListServersDetailsResponse response = listServersDetails(service);
                    List<ServerDetail> responseServers = response.getServers();
                    if (responseServers != null && responseServers.size() > 0) {
                        String status = responseServers.get(0).getStatus();
                        if (status.equals(ServerStatusEnum.ACTIVE.name())) {
                            // 更新用户关联的云服务器状态
                            userCloudServersRelationService.updateCloudServiceStatusByServerIds(servers, ServerStatusEnum.ACTIVE);
                            break;
                        }
                    }
                    // 暂停五秒后查询
                    Thread.sleep(5 * 1000);
                }
            } catch (Exception e) {
                log.error("查询服务器状态失败");
            }
            log.debug("重启后，查询服务器状态完成");
        });
    }

    @Override
    public AjaxResult batchUpdateServersName(BatchUpdateServersNameRequestBodyDTO batchUpdateServersNameRequestBodyDTO) {
        EcsClient client = getClient(batchUpdateServersNameRequestBodyDTO.getRegionId());

        BatchUpdateServersNameRequest request = new BatchUpdateServersNameRequest();
        BatchUpdateServersNameRequestBody body = new BatchUpdateServersNameRequestBody();
        BeanUtils.copyProperties(batchUpdateServersNameRequestBodyDTO, body);
        request.setBody(body);
        BatchUpdateServersNameResponse response = null;
        try {
            response = client.batchUpdateServersName(request);
        } catch (ConnectionException | RequestTimeoutException e) {
            e.printStackTrace();
        } catch (ServiceResponseException e) {
            log.error("修改云服务器名称失败: " + e);
        }
        if (response != null) {
            return AjaxResult.success(response);
        }
        return AjaxResult.error("修改云服务器名称失败");
    }

    @Override
    public AjaxResult batchResetServersPassword(BatchResetServersPasswordRequestBodyDTO batchResetServersPasswordRequestBodyDTO) {
        EcsClient client = getClient(batchResetServersPasswordRequestBodyDTO.getRegionId());
        // 新密码的校验规则 长度为8-26位 密码至少必须包含大写字母（A-Z）、小写字母（a-z）、数字（0-9）和特殊字符（!@%-_=+[]:./?）中的三种
        String password = batchResetServersPasswordRequestBodyDTO.getNewPassword();
        if (StringUtils.isEmpty(password) || password.length() < 8 || password.length() > 26) {
            return AjaxResult.error("密码长度必须为8-26位");
        }
        if (!password.matches("^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)(?=.*[!@%-_=+\\[\\]:./?])[A-Za-z\\d!@%-_=+\\[\\]:./?]{8,26}$")) {
            return AjaxResult.error("密码至少必须包含大写字母（A-Z）、小写字母（a-z）、数字（0-9）和特殊字符（!@%-_=+[]:./?）中的三种");
        }
        // 重启服务器
        BatchRebootServersRequestBodyDTO batchRebootServersRequestBodyDTO = new BatchRebootServersRequestBodyDTO();
        batchRebootServersRequestBodyDTO.setRegionId(batchResetServersPasswordRequestBodyDTO.getRegionId());
        BatchRebootSeversOption batchRebootSeversOption = new BatchRebootSeversOption();
        batchRebootSeversOption.setServers(batchResetServersPasswordRequestBodyDTO.getServers());
        batchRebootSeversOption.setType(BatchRebootSeversOption.TypeEnum.HARD); // 强制重启
        batchRebootServersRequestBodyDTO.setReboot(batchRebootSeversOption);
        batchRebootServers(batchRebootServersRequestBodyDTO);

        BatchResetServersPasswordRequest request = new BatchResetServersPasswordRequest();
        BatchResetServersPasswordRequestBody body = new BatchResetServersPasswordRequestBody();
        BeanUtils.copyProperties(batchResetServersPasswordRequestBodyDTO, body);
        request.setBody(body);

        BatchResetServersPasswordResponse response = null;
        try {
            response = client.batchResetServersPassword(request);
        } catch (ConnectionException | RequestTimeoutException e) {
            e.printStackTrace();
        } catch (ServiceResponseException e) {
            e.printStackTrace();
            log.error("重置云服务器密码失败: " + e);
        }
        if (response != null) {
            return AjaxResult.success(response);
        }
        return AjaxResult.error("重置云服务器密码失败");
    }

    @Override
    public AjaxResult showServerRemoteConsole(ShowServerRemoteConsoleRequestDTO showServerRemoteConsoleRequestDTO) {
        EcsClient client = getClient(showServerRemoteConsoleRequestDTO.getRegionId());
        ShowServerRemoteConsoleResponse response = null;
        try {
            response = client.showServerRemoteConsole(showServerRemoteConsoleRequestDTO);
        } catch (ConnectionException | RequestTimeoutException e) {
            e.printStackTrace();
        } catch (ServiceResponseException e) {
            log.error("获取云服务器远程控制台失败: " + e);
        }
        if (response != null) {
            return AjaxResult.success(response);
        }
        return AjaxResult.error("获取云服务器远程控制台失败");
    }

    @Override
    public AjaxResult renewalResources(RenewalResourcesReqDTO renewalResourcesReqDTO) {
        AccountSetting accountSetting = settingService.getAccountSetting(SettingEnum.HUAWEI);
        ICredential auth = new GlobalCredentials()
                .withAk(accountSetting.getAccessKeyId())
                .withSk(accountSetting.getSecretAccessKey());

        BssClient client = BssClient.newBuilder()
                .withCredential(auth)
                .withRegion(BssRegion.valueOf("cn-north-1"))
                .build();
        RenewalResourcesRequest request = new RenewalResourcesRequest();
        request.withBody(renewalResourcesReqDTO);

        RenewalResourcesResponse response = null;
        try {
            response = client.renewalResources(request);
            System.out.println(response.toString());
        } catch (ConnectionException | RequestTimeoutException e) {
            e.printStackTrace();
        } catch (ServiceResponseException e) {
            log.error("续费失败: " + e);
            if ("CBC.30050006".equals(e.getErrorCode())) {
                return AjaxResult.error("华为云账号余额不足，续费失败！");
            }
            if ("CBC.99003100".equals(e.getErrorCode())) {
                return AjaxResult.error("当前操作的资源中，有资源包含在您的待支付的订单，不能进行当前操作。");
            }
        }
        if (response != null) {
            return AjaxResult.success(response);
        }
        return AjaxResult.error("续费失败");
    }

    @Override
    public AjaxResult showServerBlockDevice(ShowServerBlockDeviceRequestDTO showServerBlockDeviceRequestDTO) {
        EcsClient client = getClient(showServerBlockDeviceRequestDTO.getRegionId());

        ShowServerBlockDeviceResponse response = null;
        try {
            response = client.showServerBlockDevice(showServerBlockDeviceRequestDTO);
        } catch (ConnectionException | RequestTimeoutException e) {
            e.printStackTrace();
        } catch (ServiceResponseException e) {
            log.error("获取云服务器磁盘信息失败: " + e);
        }
        if (response != null) {
            return AjaxResult.success(response);
        }
        return AjaxResult.error("获取云服务器磁盘信息失败");
    }

    @Override
    public AjaxResult listServerBlockDevices(ListServerBlockDevicesRequest listServerBlockDevicesRequest) {
        EcsClient client = getClient(null);
        ListServerBlockDevicesResponse response = null;
        try {
            response = client.listServerBlockDevices(listServerBlockDevicesRequest);
        } catch (ConnectionException | RequestTimeoutException e) {
            e.printStackTrace();
        } catch (ServiceResponseException e) {
            log.error("获取云服务器挂载信息失败: " + e);
        }
        if (response != null) {
            return AjaxResult.success(response);
        }
        return AjaxResult.error("获取云服务器挂载信息失败");
    }

    @Override
    public AjaxResult detachServerVolume(DetachServerVolumeRequestDTO detachServerVolumeRequestDTO) {
        EcsClient client = getClient(detachServerVolumeRequestDTO.getRegionId());
        DetachServerVolumeResponse response = null;
        try {
            response = client.detachServerVolume(detachServerVolumeRequestDTO);
        } catch (ConnectionException | RequestTimeoutException e) {
            e.printStackTrace();
        } catch (ServiceResponseException e) {
            log.error("卸载云服务器磁盘失败: " + e);
        }
        if (response != null) {
            return AjaxResult.success(response);
        }
        return AjaxResult.error("卸载云服务器磁盘失败");
    }

    @Override
    public AjaxResult attachServerVolume(AttachServerVolumeRequestDTO attachServerVolumeRequestDTO) {
        EcsClient client = getClient(attachServerVolumeRequestDTO.getRegionId());
        AttachServerVolumeResponse response = null;
        try {
            response = client.attachServerVolume(attachServerVolumeRequestDTO);
        } catch (ConnectionException | RequestTimeoutException e) {
            e.printStackTrace();
        } catch (ServiceResponseException e) {
            log.error("挂载云服务器磁盘失败: " + e);
        }
        if (response != null) {
            return AjaxResult.success(response);
        }
        return AjaxResult.error("挂载云服务器磁盘失败");
    }

    // 查询可用镜像参数：
    /*{
        "__imagetype":"gold",
            "__platform":"CentOS",
            "__support_kvm":true
    }*/
    @Override
    public AjaxResult changeServerOsWithCloudInit(ChangeServerOsWithCloudInitRequestDTO changeServerOsWithCloudInitRequestDTO) {
        // 先关机再切换系统
        BatchStopServersRequestBodyDTO batchStopServersRequestBodyDTO = new BatchStopServersRequestBodyDTO();
//        BatchStopServersOption batchStopServersOption = new BatchStopServersOption();
//        ServerId serverId = new ServerId();
//        serverId.setId(changeServerOsWithCloudInitRequestDTO.getServerId());
//        batchStopServersOption.setServers(Collections.singletonList(serverId));
//        batchStopServersOption.setType(BatchStopServersOption.TypeEnum.HARD); // 强制关机
//        batchStopServersRequestBodyDTO.setOsStop(batchStopServersOption);
//
//        batchStopServersRequestBodyDTO.setRegionId(changeServerOsWithCloudInitRequestDTO.getRegionId());
//
//        AjaxResult ajaxResult = this.batchStopServers(batchStopServersRequestBodyDTO);
//        if (!ajaxResult.get("code").equals(200)) {
//            return AjaxResult.error("关机失败");
//        }
//        BatchStopServersResponse batchStopServersResponse = (BatchStopServersResponse) ajaxResult.get("data");
//        //异步切换系统
//        asynchronousChangeOperatingSystem(batchStopServersResponse.getJobId(), changeServerOsWithCloudInitRequestDTO);
        EcsClient client = getClient(changeServerOsWithCloudInitRequestDTO.getRegionId());
        ChangeServerOsWithCloudInitOption osChange = changeServerOsWithCloudInitRequestDTO.getBody().getOsChange();
        osChange.setMode("withStopServer"); //取值为withStopServer ，支持开机状态下切换弹性云服务器操作系统。
        ChangeServerOsWithCloudInitResponse response = client.changeServerOsWithCloudInit(changeServerOsWithCloudInitRequestDTO);
        if (response == null) {
            return AjaxResult.error("切换弹性云服务器操作系统失败");
        }
        return AjaxResult.success("正在切换弹性云服务器操作系统");
    }

    @Override
    public AjaxResult reinstallServerWithCloudInit(ReinstallServerWithCloudInitRequestDTO reinstallServerWithCloudInitRequestDTO) {
        AccountSetting accountSetting = settingService.getAccountSetting(SettingEnum.HUAWEI);

        EcsClient client = getClient(reinstallServerWithCloudInitRequestDTO.getRegionId());
        ReinstallServerWithCloudInitResponse response = null;
        // 获取用户信息
        Domains domains = cloudServiceService.keystoneListAuthDomains();
        if (domains == null) {
            return AjaxResult.error("获取用户信息失败");
        }
        // 设置账号
        ReinstallServerWithCloudInitOption reinstallServerWithCloudInitOption = new ReinstallServerWithCloudInitOption();
        ReinstallServerWithCloudInitRequestBody body = reinstallServerWithCloudInitRequestDTO.getBody();

        if(StringUtils.isNotEmpty(body.getOsReinstall().getAdminpass())){
            reinstallServerWithCloudInitOption.setAdminpass(body.getOsReinstall().getAdminpass());
        } else {
            reinstallServerWithCloudInitOption.setAdminpass(accountSetting.getDomainPassword());
        }
        // TODO密码
        reinstallServerWithCloudInitOption.setAdminpass(accountSetting.getDomainPassword());

        reinstallServerWithCloudInitOption.setUserid(domains.getId());
        reinstallServerWithCloudInitOption.setMode("withStopServer"); //取值为withStopServer ，支持开机状态下重装弹性云服务器。
        body.setOsReinstall(reinstallServerWithCloudInitOption);
        try {
            response = client.reinstallServerWithCloudInit(reinstallServerWithCloudInitRequestDTO);
        } catch (ConnectionException | RequestTimeoutException e) {
            e.printStackTrace();
        } catch (ServiceResponseException e) {
            log.error("重装弹性云服务器操作系统失败: " + e);
        }
        if (response != null) {
            return AjaxResult.success(response);
        }
        return AjaxResult.success("正在重装弹性云服务器操作系统");
    }

    @Override
    public AjaxResult disassociatePublicips(RegionIdDTO<DisassociatePublicipsRequest> regionIdDTO) {
        RegionIdDTO<ListPublicipsRequest> listPublicipsRequestRegionIdDTO = new RegionIdDTO<>();
        listPublicipsRequestRegionIdDTO.setRegionId(regionIdDTO.getRegionId());

        PublicipShowResp listPublicIp = getListPublicIp(regionIdDTO);

        regionIdDTO.getBody().setPublicipId(listPublicIp.getId());

        String regionId = regionIdDTO.getRegionId();
        AccountSetting accountSetting = settingService.getAccountSetting(SettingEnum.HUAWEI);
        regionId = StringUtils.isEmpty(regionId) ? accountSetting.getRegionId() : regionId;
        ICredential auth = new BasicCredentials()
                .withAk(accountSetting.getAccessKeyId())
                .withSk(accountSetting.getSecretAccessKey());

        EipClient client = EipClient.newBuilder()
                .withCredential(auth)
                .withRegion(EipRegion.valueOf(regionId))
                .build();

        DisassociatePublicipsResponse response = null;
        try {
//            response = client.disassociatePublicips(regionIdDTO.getBody());
        } catch (Exception e) {
            log.error("解绑弹性公网IP失败: " + e);
        }
        if (response != null) {
            return AjaxResult.success();
        }
        return AjaxResult.error("解绑弹性公网IP失败");
    }

    @Override
    public AjaxResult updatePrePaidBandwidth(RegionIdDTO<UpdatePrePaidBandwidthRequest> regionIdDTO) {
        String regionId = regionIdDTO.getRegionId();
        AccountSetting accountSetting = settingService.getAccountSetting(SettingEnum.HUAWEI);

        regionId = StringUtils.isEmpty(regionId) ? accountSetting.getRegionId() : regionId;
        ICredential auth = new BasicCredentials()
                .withAk(accountSetting.getAccessKeyId())
                .withSk(accountSetting.getSecretAccessKey());

        com.huaweicloud.sdk.eip.v2.EipClient client = com.huaweicloud.sdk.eip.v2.EipClient.newBuilder()
                .withCredential(auth)
                .withRegion(EipRegion.valueOf(regionId))
                .build();
        UpdatePrePaidBandwidthResponse response = null;
        try {
            PublicipShowResp listPublicIp = getListPublicIp(regionIdDTO);
            UpdatePrePaidBandwidthRequest request = regionIdDTO.getBody();
            if (StringUtils.isEmpty(request.getBody().getBandwidth().getName())) {
                request.getBody().getBandwidth().setName(listPublicIp.getBandwidthName());
            }
            String bandwidthId = listPublicIp.getBandwidthId();
            request.setBandwidthId(bandwidthId);

            UpdatePrePaidBandwidthExtendParamOption extendParam = new UpdatePrePaidBandwidthExtendParamOption();
            extendParam.setIsAutoPay(true); //自动支付
            request.getBody().setExtendParam(extendParam);
            request.getBody().getExtendParam().setIsAutoPay(true);
            response = client.updatePrePaidBandwidth(regionIdDTO.getBody());
        } catch (ConnectionException | RequestTimeoutException e) {
            e.printStackTrace();
        } catch (ServiceResponseException e) {
            log.error("更新带宽失败: " + e);
        }
        if (response != null) {
            if (response.getBandwidth() != null) {
                return AjaxResult.success();
            } else {
                return AjaxResult.error("总帐号余额不足，请联系管理员充值并支付订单");
            }
        }
        return AjaxResult.error("更新带宽失败");
    }
    @Override
    public AjaxResult showBandwidth(RegionIdDTO<ShowBandwidthRequest> regionIdDTO) {
        String regionId = regionIdDTO.getRegionId();
        AccountSetting accountSetting = settingService.getAccountSetting(SettingEnum.HUAWEI);

        regionId = StringUtils.isEmpty(regionId) ? accountSetting.getRegionId() : regionId;
        ICredential auth = new BasicCredentials()
                .withAk(accountSetting.getAccessKeyId())
                .withSk(accountSetting.getSecretAccessKey());

        com.huaweicloud.sdk.eip.v2.EipClient client = com.huaweicloud.sdk.eip.v2.EipClient.newBuilder()
                .withCredential(auth)
                .withRegion(EipRegion.valueOf(regionId))
                .build();
        ShowBandwidthResponse response = null;
        try {
            ShowBandwidthRequest request = regionIdDTO.getBody();

            response = client.showBandwidth(request);
        }catch (ServiceResponseException e) {
            log.error("查询带宽失败: " + e);
        }
        if (response != null) {
            if (response.getBandwidth() != null) {
                return AjaxResult.success(response);
            } else {
                return AjaxResult.error("总帐号余额不足，请联系管理员充值并支付订单");
            }
        }
        return AjaxResult.error("查询带宽失败");
    }

    @Override
    public AjaxResult listResizeFlavors(RegionIdDTO<UpdatePrePaidBandwidthRequest> regionIdDTO) {
        String regionId = regionIdDTO.getRegionId();
        EcsClient client = getClient(regionId);
        ListResizeFlavorsRequest request = new ListResizeFlavorsRequest();
        ListResizeFlavorsResponse response;
        try {
            response = client.listResizeFlavors(request);
        }catch (ConnectionException | RequestTimeoutException | ServiceResponseException e) {
            e.printStackTrace();
            throw new ServiceException(e.getMessage());
        }
        return AjaxResult.success(response);
    }

    @Override
    public ListVpcsResponse listVpcs(RegionIdDTO<UpdatePrePaidBandwidthRequest> regionIdDTO) {
        String regionId = regionIdDTO.getRegionId();
        VpcClient client = getVpcClient(regionId);
        ListVpcsRequest request = new ListVpcsRequest();
        ListVpcsResponse response;
        try {
            response = client.listVpcs(request);
        }catch (ConnectionException | RequestTimeoutException | ServiceResponseException e) {
            e.printStackTrace();
            throw new ServiceException(e.getMessage());
        }
        return response;
    }

    @Override
    public ShowServerResponse showServer(RegionIdDTO<ShowServerRequest> regionIdDTO) {
        String regionId = regionIdDTO.getRegionId();
        EcsClient client = getClient(regionId);
        ShowServerRequest request = regionIdDTO.getBody();
        ShowServerResponse response = client.showServer(request);
        return response;
    }

    @Override
    public ListPublicipsResponse listPublicips(RegionIdDTO<ListPublicipsRequest> regionIdDTO) {

        String regionId = regionIdDTO.getRegionId();
        AccountSetting accountSetting = settingService.getAccountSetting(SettingEnum.HUAWEI);
        regionId = StringUtils.isEmpty(regionId) ? accountSetting.getRegionId() : regionId;
        ICredential auth = new BasicCredentials()
                .withAk(accountSetting.getAccessKeyId())
                .withSk(accountSetting.getSecretAccessKey());

        com.huaweicloud.sdk.eip.v2.EipClient client = com.huaweicloud.sdk.eip.v2.EipClient.newBuilder()
                .withCredential(auth)
                .withRegion(EipRegion.valueOf(regionId))
                .build();

        try {
            ListPublicipsResponse response = client.listPublicips(regionIdDTO.getBody());
            System.out.println(response.toString());
            return response;
        } catch (ConnectionException e) {
            e.printStackTrace();
        } catch (RequestTimeoutException e) {
            e.printStackTrace();
        } catch (ServiceResponseException e) {
            e.printStackTrace();
        }
        return null;
    }

    @Override
    public CreateVolumeResponse createVolume(RegionIdDTO<CreateVolumeRequest> regionIdDTO) {

        String regionId = regionIdDTO.getRegionId();
        AccountSetting accountSetting = settingService.getAccountSetting(SettingEnum.HUAWEI);
        regionId = StringUtils.isEmpty(regionId) ? accountSetting.getRegionId() : regionId;
        ICredential auth = new BasicCredentials()
                .withAk(accountSetting.getAccessKeyId())
                .withSk(accountSetting.getSecretAccessKey());
        EvsClient client = EvsClient.newBuilder()
                .withCredential(auth)
                .withRegion(EvsRegion.valueOf(regionId))
                .build();

        CreateVolumeRequest request = regionIdDTO.getBody();
        try {
            CreateVolumeResponse response = client.createVolume(request);
            return response;
        } catch (ConnectionException e) {
            e.printStackTrace();
        } catch (RequestTimeoutException e) {
            e.printStackTrace();
        } catch (ServiceResponseException e) {
            e.printStackTrace();
        }
        return null;
    }

    private EcsClient getClient(String regionId) {
        AccountSetting accountSetting = settingService.getAccountSetting(SettingEnum.HUAWEI);
        regionId = StringUtils.isEmpty(regionId) ? accountSetting.getRegionId() : regionId;
        ICredential auth = new BasicCredentials()
                .withAk(accountSetting.getAccessKeyId())
                .withSk(accountSetting.getSecretAccessKey());

        return EcsClient.newBuilder()
                .withCredential(auth)
                .withRegion(EcsRegion.valueOf(regionId))
                .build();
    }
    private VpcClient getVpcClient(String regionId) {
        AccountSetting accountSetting = settingService.getAccountSetting(SettingEnum.HUAWEI);
        regionId = StringUtils.isEmpty(regionId) ? accountSetting.getRegionId() : regionId;
        ICredential auth = new BasicCredentials()
                .withAk(accountSetting.getAccessKeyId())
                .withSk(accountSetting.getSecretAccessKey());

        return VpcClient.newBuilder()
                .withCredential(auth)
                .withRegion(VpcRegion.valueOf(regionId))
                .build();
    }

    /**
     * 异步切换系统
     */
    public void asynchronousChangeOperatingSystem(String jobId, ChangeServerOsWithCloudInitRequestDTO changeServerOsWithCloudInitRequestDTO) {
        ThreadUtil.execAsync(() -> {
            ShowJobResponse showJobResponse = null;
            try {
                ListServersDetailsRequestDTO listServersDetailsRequestDTO = new ListServersDetailsRequestDTO();
                listServersDetailsRequestDTO.setRegionId(changeServerOsWithCloudInitRequestDTO.getRegionId());
                listServersDetailsRequestDTO.setServerId(changeServerOsWithCloudInitRequestDTO.getServerId());
                ListServersDetailsResponse listServersDetailsResponse = this.listServersDetails(listServersDetailsRequestDTO);
                if (listServersDetailsResponse == null) {
                    return;
                }
                String status = listServersDetailsResponse.getServers().get(0).getStatus();
                // 如果云服务器未关机，等待关机完成
                if (!status.equals("SHUTOFF")) {
                    do {
                        log.debug("关机中...");
                        showJobResponse = cloudServiceService.showJob(jobId, changeServerOsWithCloudInitRequestDTO.getRegionId());
                        Thread.sleep(5 * 1000); // 5秒查询一次
                    } while (showJobResponse.getStatus().equals(ShowJobResponse.StatusEnum.RUNNING));
                }
                log.debug("正在切换弹性云服务器操作系统");
                EcsClient client = getClient(changeServerOsWithCloudInitRequestDTO.getRegionId());
                ChangeServerOsWithCloudInitResponse response = client.changeServerOsWithCloudInit(changeServerOsWithCloudInitRequestDTO);
                if (response != null) {
                    log.debug("切换弹性云服务器操作系统成功");
                }
            } catch (Exception e) {
                log.error("切换弹性云服务器操作系统: " + e);
            }
        });
    }

    /**
     * 获取公网IP
     *
     * @param regionIdDTO_ 公网IP
     * @return 公网IP
     */
    private PublicipShowResp getListPublicIp(RegionIdDTO regionIdDTO_) {
        RegionIdDTO<ListPublicipsRequest> regionIdDTO = new RegionIdDTO<>();
        ListPublicipsRequest listPublicipsRequest = new ListPublicipsRequest();
        regionIdDTO.setBody(listPublicipsRequest);
        regionIdDTO.setRegionId(regionIdDTO_.getRegionId());
        // 获取公网IP
        Map<String, Object> params = regionIdDTO_.getParams();
        if (params != null) {
            String publicIp = (String) params.get("publicIp");
            if (StringUtils.isNotEmpty(publicIp)) {
                listPublicipsRequest.setPublicIpAddress(Collections.singletonList(publicIp));
            }
        } else {
            throw new ServiceException("公网IP不能为空");
        }
        List<PublicipShowResp> publicipShowResps = cloudServiceService.listPublicips(regionIdDTO);
        if (publicipShowResps == null || publicipShowResps.size() == 0) {
            throw new ServiceException("公网IP不存在");
        }
        return publicipShowResps.get(0);
    }
}
